import pyb, utime
import firmwareupdate
import rtc_wake
import sx126x
from machine import SPI
from pyb import Pin, ExtInt, LED, Timer
from pwscrypt import PWSCrypt
from getFirmware import OTA
import pwsutil

import binascii

NODE_ID = const(0x01)
HOST_ID = const(0x00)

_rssi = 0
_snr = 0

_count_no = 0			# 发送包计数器

def _packBeacon():
	global _count_no

	data = bytearray(4)

	data[0] = 0
	data[1] = _count_no
	data[2] = _rssi
	data[3] = _snr

	_count_no = (_count_no + 1) & 0xFF

	return data

def _sendData(buf):
	sx126x.Send(buf, 0xFFFF)

	# wait for TX done
	while True:
		utime.sleep_ms(1)
		irqStatus = sx126x.GetIrqStatus()
		if ((irqStatus & sx126x.IRQ_TX_DONE) == sx126x.IRQ_TX_DONE):
			break
	return

def _recvData():
	# sx126x.SetRx(3200, True)		# Timeout 50ms
	sx126x.SetRx(6400, True)		# Timeout 100ms
	ret = False
	_data = None

	# wait for RX Done	(最大等待200ms，避免异常)
	for _ in range(200):
		utime.sleep_ms(1)
		irqStatus = sx126x.GetIrqStatus()
		# print(hex(irqStatus))
		if ((irqStatus & sx126x.IRQ_RX_TX_TIMEOUT) == sx126x.IRQ_RX_TX_TIMEOUT):
			break

		if ((irqStatus & sx126x.IRQ_RX_DONE) == sx126x.IRQ_RX_DONE):
			recvData = sx126x.Recv()
			# 判断是否本机接收
			# 至少 1 + 1 + 8 + 16 + 2字节
			if (len(recvData) < 28):
				ret = False
				break

			if ((recvData[0] == NODE_ID) or (recvData[1] != NODE_ID)):
				ret = False
				break

			#解密
			data = crypt.decrypt(recvData)
			ret = data[0]
			if (ret):
				_data = data[1]
			break
	
	return ret, _data

def _updateFW(data):
	global _count_no

	# 进入升级流程（和常规不同，这里不会退出。除非多次超时）
	_ver = (data[3] << 24) + (data[4] << 16) + (data[5] << 8) + data[6]
	_size = (data[7] << 24) + (data[8] << 16) + (data[9] << 8) + data[10]
	_tag = data[11:27]
	print("ver=", _ver)
	print("size=", _size)
	print("tag=", binascii.hexlify(_tag))

	ota = OTA(_sendData, _recvData, crypt, 3)

	last = False

	while True:
		ret = ota.getFirmware([_ver, _size, _tag], _count_no)
		_count_no = (_count_no + 1) & 0xFF
		if (ret[0]):
			last = ret[1]
			if (last):
				break
		else:
			break

	if (last):
		print("ready")
		if (firmwareupdate.update('/data/firmware.bin', _tag)):
			print("reboot")
			pyb.hard_reset()
		else:
			print("update failed!")

	return

def _procData(data):
	print(binascii.hexlify(data))
	pwsutil.writeBKSRAM(1, 1)		# 有接收到数据

	_cmd = data[2]
	if (_cmd == 0x00):
		return

	if (_cmd == 0x01):
		# New firmware
		_updateFW(data)
		return

	if (_cmd == 0x02):
		# Reboot
		pyb.hard_reset()
		return

# poweron
PowerPin = Pin('B10', Pin.OUT_PP)
PowerPin.on()

utime.sleep_ms(500)

spi = SPI(2)
spi.init(baudrate=10000000)

sx126x.Init(spi, rst='A15', nss='B12', busy='B4')
sx126x.Begin(freq=434000000, power=22)

def extint_cb(l):
	LED(2).off()

ExtInt(Pin('B3'), ExtInt.IRQ_RISING, Pin.PULL_NONE, extint_cb)

crypt = PWSCrypt()

while True:
	pyb.stop()
	utime.sleep_ms(1)
	if (not rtc_wake.wake):
		continue
	
	rtc_wake.wake = False

	# 打包发送
	data = _packBeacon()
	buf = crypt.encrypt(data)

	for i in range(2):
		LED(2).on()
		_sendData(buf)

		# 等待确认（超时重发）
		LED(3).on()
		data = _recvData()
		LED(3).off()

		ret = data[0]
		if (ret):
			break
	
	if (ret):
		# 成功接收数据，进行处理
		_procData(data[1])


	if pyb.Switch().value():
		break
	pyb.LED(1).toggle()
	print("!!!", pyb.RTC().datetime())
